package JAVA300.第十二章网络编程;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 在线聊天室：服务器端
 * ---实现多个客户可以群发，外加可以选择私聊
 * 约定：私聊形式 @name：---给server之后--拆分处名字啊在容器里找名字--对点发送
 * 主要在sendOthers函数改就行
 * --------没办法选择私聊
 *
 */

public class web05_TCP6_Chat7Server {
    private static CopyOnWriteArrayList<Channel> socketList = new CopyOnWriteArrayList<>();
    public static void main(String[] args) throws IOException {

        System.out.println("--------Server-----------");
        //1。指定端口 使用ServerSocket创建服务器
        //***添加while

        ServerSocket server = new ServerSocket(9796);
            while (true) {
                //2.阻塞式的等待链接 accept
                Socket socket = server.accept();
                System.out.println("一个客户端建立了连接");
                Channel c = new Channel(socket);
                socketList.add(c);//交给容器管理

                new Thread(c).start();

//线程封装                new Thread(()->{
//                //3接收消息
//
////         封装进构造器           DataInputStream dis = null;
////                    DataOutputStream dos =null;
////                    try {
////                        dis = new DataInputStream(socket.getInputStream());
////                        dos = new DataOutputStream(socket.getOutputStream());
////                    } catch (IOException e) {
////                        e.printStackTrace();
////                    }
//                    //4返回消息
//
//                    //线程run操作
//                boolean isRunning = true;
//                while (isRunning) {
//                    String msg = null;
//                    try {
//                        //接收消息
//       //                 msg = dis.readUTF();
//                        //发送消息
//       //                 dos.writeUTF(msg);
//       //                 dos.flush();
//                    } catch (IOException e) {
//                        e.printStackTrace();
//                        //出问题
//                        isRunning = false;
//                    }
//
//
//                }
//                //5释放资源-借助带有可变参数的工具类函数进行封装
//
//        }).start();

    }

    }

    static class Channel implements Runnable{
        private DataInputStream dis;
        private DataOutputStream dos;
        private Socket socket;
        private boolean isRunning;
        private String name;

        public Channel(Socket socket) {//在new对象但是未开启线程的时候
            this.socket = socket;
            //接收名称

            isRunning =true;

            try {
                dis = new DataInputStream(socket.getInputStream());
                dos = new DataOutputStream(socket.getOutputStream());
                this.name = receive();//receive用到dis 所以一定要放在后面！！！
                //******欢迎标语--自身管道
                this.send("欢迎"+name+"到来！");
                //**************添加标志 表示是否为系统消息
                SendOthers(name +"已经上线！",true);
               // SendOthers("");
            } catch (IOException e) {
               // e.printStackTrace();
                System.out.println("---error Channel-----");
                //出错了
                release();
            }

        }

        //接收数据
        private String receive(){

            String getMsg ="";//避免空指针
            try {
                getMsg=  this.dis.readUTF();
                return getMsg;
            } catch (IOException e) {
                System.out.println("---error receive-----");
                release();
            }
            return getMsg;

        }

        //返回数据
        private void send(String sendMsg){
            try {
                dos.writeUTF(sendMsg);
                dos.flush();
            } catch (IOException e) {
                System.out.println("---error send-----");
                release();
            }

        }
        //群聊--服务器的receive传给其他的send
        //*********判断是不是私聊
        private void SendOthers(String msg,boolean sys){
            boolean privateChat = msg.startsWith("@");
            if (privateChat){
                int index  = msg.indexOf(":");
                //获取目标
                String targetName = msg.substring(1,index);
                msg= msg.substring(index+1);
                //遍历
                for (Channel other:socketList){
                    if (other.name.equals(targetName)){
                        other.send(this.name + "单聊你：" + msg);
                    }else {
                        continue;
                    }
                }

            }else {

                for (Channel other : socketList) {
                    if (other == this) {
                        continue;
                    }
                    if (!sys) {
                        other.send(this.name + "发来了：" + msg);
                    } else {
                        other.send(msg);
                    }

                }


            }
        }


        //释放资源-释放资源-借助带有可变参数的工具类函数进行封装
        private void release(){
            this.isRunning = false;
            web_TCPChatUntils.close(dos,dis,socket);
            //********退出之后还需要从容器删除
            socketList.remove(this);
            SendOthers(this.name+"下线拉！",true);

        }

        @Override
        public void run() {

            while (this.isRunning){
                String getMsg =receive();
                if (!getMsg.equals("")){
                    //send(getMsg);
                    SendOthers(getMsg,false);
                }
            }

        }
    }
}
